Inside Macintosh: Memory

Previous | Chapter Top | Chapter Contents | Next

Determining the Amount of Free Memory

Because space in your heap is limited, you cannot usually honor every user request that would require your application to allocate memory. For example, every time the user opens a new window, you probably need to allocate a new window record and other associated data structures. If you allow the user to open windows endlessly, you risk running out of memory. This might adversely affect your application's ability to perform important operations such as saving existing data in a window.

It is important, therefore, to implement some scheme that prevents your application from using too much of its own heap. One way to do this is to maintain a memory cushion that can be used only to satisfy essential memory requests. Before allocating memory for any nonessential task, you need to ensure that the amount of memory that remains free after the allocation exceeds the size of your memory cushion. You can do this by calling the function IsMemoryAvailable defined in Listing 1-5 .

Listing 5 Determining whether allocating memory would deplete the memory cushion

FUNCTION IsMemoryAvailable (memRequest: LongInt): Boolean;
VAR
    total:      LongInt;        {total free memory if heap purged}
    contig:     LongInt;        {largest contiguous block if heap purged}
BEGIN
    PurgeSpace(total, contig);
    IsMemoryAvailable := ((memRequest + kMemCushion) < contig);
END;

The IsMemoryAvailable function calls the Memory Manager's PurgeSpace procedure to determine the size of the largest contiguous block that would be available if the application heap were purged; that size is returned in the contig parameter. If the size of the potential memory request together with the size of the memory cushion is less than the value returned in contig , IsMemoryAvailable is set to TRUE , indicating that it is safe to allocate the specified amount of memory; otherwise, IsMemoryAvailable returns FALSE .

Notice that the IsMemoryAvailable function does not itself cause the heap to be purged or compacted; the Memory Manager does so automatically when you actually attempt to allocate the memory.

Usually, the easiest way to determine how big to make your application's memory cushion is to experiment with various values. You should attempt to find the lowest value that allows your application to execute successfully no matter how hard you try to allocate memory to make the application crash. As an extra guarantee against your application's crashing, you might want to add some memory to this value. As indicated earlier in this chapter, 40 KB is a reasonable size for most applications.

CONST
    kMemCushion =       40 * 1024;                  {size of memory cushion}

You should call the IsMemoryAvailable function before all nonessential memory requests, no matter how small. For example, suppose your application allocates a new, small relocatable block each time a user types a new line of text. That block might be small, but thousands of such blocks could take up a considerable amount of space. Therefore, you should check to see if there is sufficient memory available before allocating each one. (See Listing 1-6 on Allocating relocatable blocks for an example of how to call IsMemoryAvailable .)

You should never, however, call the IsMemoryAvailable function before an essential memory request. When deciding how big to make the memory cushion for your application, you must make sure that essential requests can never deplete all of the cushion. Note that when you call the IsMemoryAvailable function for a nonessential request, essential requests might have already dipped into the memory cushion. In that case, IsMemoryAvailable returns FALSE no matter how small the nonessential request is.

Some actions should never be rejectable. For example, you should guarantee that there is always enough memory free to save open documents, and to perform typical maintenance tasks such as updating windows. Other user actions are likely to be always rejectable. For example, because you cannot allow the user to create an endless number of documents, you should make the New Document and Open Document menu commands rejectable.

Although the decisions of which actions to make rejectable are usually obvious, modal and modeless boxes present special problems. If you want to make such dialog boxes available at all costs, you must ensure that you allocate a large enough memory cushion to handle the maximum number of these dialog boxes that the user could open at once. If you consider a certain dialog box (for instance, a spelling checker) nonessential, you must be prepared to inform the user that there is not enough memory to open it if memory space become low.


© 1997 Apple Computer, Inc.

Previous | Chapter Top | Chapter Contents | Next